<?php

namespace app\api\common;

use app\common\exception\ApiException;

class TokenManager
{
    const TOKEN_ERR = '10001';
    private static $_obj = null;
    private $_header_name = 'access_token';
    private $_access_token = '';//UID-TIME-XXXXAAAABBBBCCCC
    private $_uid = 0;
    private $_time = 0;

    /**
     * 实例化
     * @return TokenManager
     */
    public static function instance()
    {
        if (self::$_obj === null) {
            self::$_obj = new TokenManager();
        }
        return self::$_obj;
    }

    private function _getPostToken()
    {
        $access_token = input($this->_header_name, '');
        return $access_token;
    }

    public function check()
    {
        $this->_access_token = $this->_getPostToken();
        if (!$this->_access_token) {
            throw new ApiException(['msg' => $this->_header_name . ' 不可以为空', 'errorCode' => self::TOKEN_ERR]);
        }

        $token_arr = explode('-', $this->_access_token);
        if (count($token_arr) != 3) {
            throw new ApiException(['msg' => $this->_header_name . ' 无效', 'errorCode' => self::TOKEN_ERR]);
        }

        $this->_uid = $token_arr[0];
        $this->_time = $token_arr[1];

        if ($this->_genToken($token_arr[0], $this->_time) != $this->_access_token) {
            throw new ApiException(['msg' => $this->_header_name . ' 验证失败', 'errorCode' => self::TOKEN_ERR]);
        }

        //token超过24小时
        if (time() - $this->_time >= 86400) {
            throw new ApiException(['msg' => $this->_header_name . ' 过期', 'errorCode' => self::TOKEN_ERR]);
        }

        $user = \app\api\model\Admin::where('id', $this->_uid)->find();

        //其它地方登录，token过期
        if (!$user) {
            throw new ApiException(['msg' => $this->_header_name . ' 过期', 'errorCode' => self::TOKEN_ERR]);
        }

        if ($user['token'] != $this->_access_token) {
            throw new ApiException(['msg' => $this->_header_name . ' 过期', 'errorCode' => self::TOKEN_ERR]);
        }

        //token超过30天
        if (time() - $user['token_time'] >= 86400 * 30) {
            throw new ApiException(['msg' => $this->_header_name . ' 过期', 'errorCode' => self::TOKEN_ERR]);
        }
    }

    private function _genToken($uid, $time)
    {
        return $uid . '-' . $time . '-' . sha1('HSERVER_' . md5($uid . '_h_' . $time));
    }

    /**
     * 获取access_token
     * @param $uid
     * @return string
     */
    public function genAccessToken($uid)
    {
        if (!$uid) {
            throw new ApiException(['msg' => 'uid错误', 'errorCode' => self::TOKEN_ERR]);
        }

        $this->_uid = $uid;
        $this->_time = time();
        $this->_access_token = $this->_genToken($this->_uid, $this->_time);

        $rst = \app\api\model\Admin::update(['token' => $this->_access_token, 'token_time' => $this->_time], ['id' => $this->_uid]);
        if (!$rst) {
            throw new ApiException(['access_token 生成失败']);
        }

        return $this->_access_token;
    }

    /**
     * 获取用户ID
     * @return int
     */
    public function getUid()
    {
        return $this->_uid;
    }

    /**
     * 获取token生成的时间
     * @return int
     */
    public function getTokenTime()
    {
        return $this->_time;
    }

    /**
     * 获取token过期时间
     * @return int
     */
    public function getTokenExpireTime()
    {
        return $this->getTokenTime() + 79200;
    }
}